package com.gitee.taotaojs.util.date;

import com.gitee.taotaojs.exception.MyInnerException;
import com.gitee.taotaojs.util.ConstantUtil;

import java.util.Calendar;
import java.util.Date;

/**
 * 时间段工具类
 * <ol>
 * <li>获取某单位时间的最大最小值</li>
 * <li>获取包含某个时间的某单位时间段【byAIGetDate】</li>
 * <li>获取两个时间的月份差</li>
 * </ol>
 * @author TaoTaojs
 * @Date 2019年11月19日10:45:39
 * 关联类
 * 参考链接
 */
public class CalendarStateUtil {

	/** 日期 */
	public static final int DATE = 1;
	/** 星期 */
	public static final int WEEK = 2;
	/** 月份 */
	public static final int MONTH = 3;
	/** 年份 */
	public static final int YEAR = 4;
	/** 季度 */
	public static final int QUARTER = 5;
	/** 半年 */
	public static final int HALFYEAR = 6;

	CalendarStateUtil() {

	}

	/**
	 * 获取本小时0分
	 * @param date 指定时间
	 * @return 本小时0分
	 */
	public static Date getHourTimeStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取本小时59分
	 * @param date 指定时间
	 * @return 本小时59分
	 */
	public static Date getHourTimeStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		calendar.set(Calendar.MINUTE, calendar.getActualMaximum(Calendar.MINUTE));
		calendar.set(Calendar.SECOND, calendar.getActualMaximum(Calendar.SECOND));
		calendar.set(Calendar.MILLISECOND, calendar.getActualMaximum(Calendar.MILLISECOND));
		return calendar.getTime();
	}

	/**
	 * 获取本分钟0秒
	 * @param date 指定时间
	 * @return 本分钟0秒
	 */
	public static Date getMinuteTimeStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取本分钟第59秒
	 * @param date 指定时间
	 * @return 本分钟59秒
	 */
	public static Date getMinuteTimeStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		calendar.set(Calendar.SECOND, calendar.getActualMaximum(Calendar.SECOND));
		calendar.set(Calendar.MILLISECOND, calendar.getActualMaximum(Calendar.MILLISECOND));
		return calendar.getTime();
	}

	/**
	 * 将（某天）时间设置为最大
	 * @param calendar 指定时间
	 */
	private static void setMaxDate(Calendar calendar){
		calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMaximum(Calendar.HOUR_OF_DAY));
		calendar.set(Calendar.MINUTE, calendar.getActualMaximum(Calendar.MINUTE));
		calendar.set(Calendar.SECOND, calendar.getActualMaximum(Calendar.SECOND));
		calendar.set(Calendar.MILLISECOND, calendar.getActualMaximum(Calendar.MILLISECOND));
	}
	/**
	 * 将（某天）时间设置为最小
	 * @param calendar 指定时间
	 */
	private static void setMinDate(Calendar calendar){
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
	}

	/**
	 * 当天0点
	 * @param date 指定时间
	 * @return 当天0点
	 */
	public static Date getDateStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMinDate(calendar);
		return calendar.getTime();
	}

	/**
	 * 当天23:59:59
	 * @param date 指定时间
	 * @return 当天最后一秒
	 */
	public static Date getDateStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMaxDate(calendar);
		return calendar.getTime();
	}

	/**
	 * 本周第一天
	 * @param date 指定时间
	 * @return 本周第一天
	 */
	public static Date getWeekStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMinDate(calendar);
		int week = calendar.get(Calendar.DAY_OF_WEEK);
		calendar.add(Calendar.DATE, -week+2);
		return calendar.getTime();
	}

	/**
	 * 本周最后一天
	 * @param date 指定时间
	 * @return 本周最后一天
	 */
	public static Date getWeekStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMaxDate(calendar);
		int week = calendar.get(Calendar.DAY_OF_WEEK);
		calendar.add(Calendar.DATE, -week+2+6);
		return calendar.getTime();
	}

	/**
	 * 本月第一天
	 * @param date 指定时间
	 * @return 本月第一天
	 */
	public static Date getMouseStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMinDate(calendar);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar.getTime();
	}

	/**
	 * 本月最后一天
	 * @param date 指定时间
	 * @return 本月最后一天
	 */
	public static Date getMouseStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMaxDate(calendar);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

    /**
     * 本季度第一天
     * @param date 指定时间
     * @return 本季度第一天
     */
    public static Date getQuarterStart(Date date){
        Calendar calendar = CalendarUtil.getCalendar(date);
        setMinDate(calendar);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH)/3*3);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 本季度最后一天
     * @param date 指定时间
     * @return 本季度最后一天
     */
    public static Date getQuarterStop(Date date){
        Calendar calendar = CalendarUtil.getCalendar(date);
        setMaxDate(calendar);
        calendar.set(Calendar.MONTH, (calendar.get(Calendar.MONTH)/3 + 1)*3 - 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

	/**
	 * 本半年第一天
	 * @param date 指定时间
	 * @return 本半年最后一天
	 */
	public static Date getHalfYearStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMinDate(calendar);
		calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH)/6*6);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar.getTime();
	}

	/**
	 * 本半年最后一天
	 * @param date 指定时间
	 * @return 本半年最后一天
	 */
	public static Date getHalfYearStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMaxDate(calendar);
		calendar.set(Calendar.MONTH, (calendar.get(Calendar.MONTH)/6 + 1)*6 - 1);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	/**
	 * 本年第一天
	 * @param date 指定时间
	 * @return 本年第一天
	 */
	public static Date getYearStart(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMinDate(calendar);
		calendar.set(Calendar.DAY_OF_YEAR, 1);
		return calendar.getTime();
	}

	/**
	 * 本年最后一天
	 * @param date 指定时间
	 * @return 本年最后一天
	 */
	public static Date getYearStop(Date date){
		Calendar calendar = CalendarUtil.getCalendar(date);
		setMaxDate(calendar);
		calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
		return calendar.getTime();
	}

	/**
	 * 根据model类型，获取当前时间的某个时间段
	 * @param date 时间段中包含的一个时间点
	 * @param model 具体参考静态属性
	 * @return 自动判断类型并返回时间段
	 */
	public static Date[] byAiGetDate(Date date, int model) {
		if(model == DATE) {
			return new Date[]{getDateStart(date), getDateStop(date)};
		}else if(model == MONTH) {
			return new Date[]{getMouseStart(date), getMouseStop(date)};
		}else if(model == WEEK) {
			return new Date[]{getWeekStart(date), getWeekStop(date)};
		}else if(model == YEAR) {
			return new Date[]{getYearStart(date), getYearStop(date)};
		}else if(model == QUARTER) {
			return new Date[]{getQuarterStart(date), getQuarterStop(date)};
		}else if(model == HALFYEAR) {
			return new Date[]{getHalfYearStart(date), getHalfYearStop(date)};
		}else{
			throw new MyInnerException("参数不正确！请检查");
		}
	}

	/**
	 * 获取两个时间的月份差
	 * @param startData 开始时间
	 * @param stopData 结束时间
	 * @return 结束时间-开始时间 = 正数，开始时间小于结束时间，，负数，开始时间大于结束时间
	 */
	public static int getDifferMonth(Date startData, Date stopData){
		//固定的某个日期
		Calendar start  = Calendar.getInstance();
		//当前的日期
		Calendar stop = Calendar.getInstance();
		start.setTime(startData);
		stop.setTime(stopData);
		int result = (stop.get(Calendar.MONTH) - start.get(Calendar.MONTH));
		int month = (stop.get(Calendar.YEAR) - start .get(Calendar.YEAR))*(ConstantUtil.TEN + ConstantUtil.TWO);
		return result + month;
	}

	/**
	 * 获取两个时间的月份差（已经绝对值了）
	 * @param afterData 开始时间
	 * @param beforeData 结束时间
	 * @return 时间int差
	 */
	public static int getDifferMonthAbs(Date afterData, Date beforeData){
		return Math.abs(getDifferMonth(afterData, beforeData));
	}

}
